#include "Common.fxh"

SamplerState Trilinear
{
	Filter = MIN_MAG_MIP_LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};

Texture3D gLightTex0;
Texture3D gLightTex1;
Texture3D gLightTex2;
Texture3D gLightTex3;
Texture3D gLightTex4;
Texture3D gLightTex5;

float3 gLightVolPos;
float3 gLightVolScale;

float3 gEyePosW;

cbuffer cbPerObject
{
	float4x4 gWVP;
	float4x4 gWorld;
};

struct VS_IN
{
	float3 posL     : POSITION;
	float3 normalL  : NORMAL0;
	float3 tangentL : TANGENT0;
	float2 texCoord : TEXCOORD0;
};

struct VS_OUT
{
	float4 posD         : SV_POSITION;
	float3 posW         : TEXCOORD0;
	float3 normalW      : TEXCOORD1;
};

VS_OUT VS(VS_IN vIn)
{
	VS_OUT vOut;

	vOut.posD = mul(float4(vIn.posL, 1.0f), gWVP);
	vOut.posW = mul(float4(vIn.posL, 1.0f), gWorld).xyz;
	vOut.normalW = normalize(mul(float4(vIn.normalL, 0.0f), gWorld).xyz);

	return vOut;
}

float4 PS(VS_OUT pIn) : SV_Target
{
	const float VOLUME_SIZE = 16;

	float3 lightVolSpacePos = (pIn.posW - gLightVolPos) / gLightVolScale;

	if( lightVolSpacePos.x > VOLUME_SIZE-1 || lightVolSpacePos.x < 0 ||
		lightVolSpacePos.y > VOLUME_SIZE-1 || lightVolSpacePos.y < 0 ||
		lightVolSpacePos.z > VOLUME_SIZE-1 || lightVolSpacePos.z < 0)
	{
		return float4(1.0f, 0.0f, 1.0f, 1.0f);
	}

	lightVolSpacePos /= VOLUME_SIZE;

	float3 lightAcc = float3(0, 0, 0);
	float3 N = normalize(pIn.normalW);

	const float3 XPOS = float3(1, 0, 0);
	const float3 YPOS = float3(0, 1, 0);
	const float3 ZPOS = float3(0, 0, 1);
	const float3 XNEG = float3(-1, 0, 0);
	const float3 YNEG = float3(0, -1, 0);
	const float3 ZNEG = float3(0, 0, -1);

	lightAcc += saturate(N.x * gLightTex0.Sample(Trilinear, lightVolSpacePos).rgb);
	lightAcc += saturate(N.y * gLightTex1.Sample(Trilinear, lightVolSpacePos).rgb);
	lightAcc += saturate(N.z * gLightTex2.Sample(Trilinear, lightVolSpacePos).rgb);
	lightAcc += saturate(-N.x * gLightTex3.Sample(Trilinear, lightVolSpacePos).rgb);
	lightAcc += saturate(-N.y * gLightTex4.Sample(Trilinear, lightVolSpacePos).rgb);
	lightAcc += saturate(-N.z * gLightTex5.Sample(Trilinear, lightVolSpacePos).rgb);

	//float3 viewRayW = normalize(pIn.posW - gEyePosW);
	//float3 lightDirReflW;
//
	//lightDirReflW = reflect(XPOS, N);
	//lightAcc += pow( saturate(dot(viewRayW, lightDirReflW)), 128 ) * gLightTex0.Sample(Trilinear, lightVolSpacePos).rgb;
//
	//lightDirReflW = reflect(YPOS, N);
	//lightAcc += pow( saturate(dot(viewRayW, lightDirReflW)), 128 ) * gLightTex1.Sample(Trilinear, lightVolSpacePos).rgb;
//
	//lightDirReflW = reflect(ZPOS, N);
	//lightAcc += pow( saturate(dot(viewRayW, lightDirReflW)), 128 ) * gLightTex2.Sample(Trilinear, lightVolSpacePos).rgb;
//
	//lightDirReflW = reflect(XNEG, N);
	//lightAcc += pow( saturate(dot(viewRayW, lightDirReflW)), 128 ) * gLightTex3.Sample(Trilinear, lightVolSpacePos).rgb;
//
	//lightDirReflW = reflect(YNEG, N);
	//lightAcc += pow( saturate(dot(viewRayW, lightDirReflW)), 128 ) * gLightTex4.Sample(Trilinear, lightVolSpacePos).rgb;
//
	//lightDirReflW = reflect(ZNEG, N);
	//lightAcc += pow( saturate(dot(viewRayW, lightDirReflW)), 128 ) * gLightTex5.Sample(Trilinear, lightVolSpacePos).rgb;

	//float3 xPosC = float3(0.5 / 3.7416f + 0.6f, 0 + 0.6f, 0 + 0.6f);
	//float3 yPosC = float3(1.0 / 3.7416f + 0.6f, 0 + 0.6f, 0 + 0.6f);
	//float3 zPosC = float3(1.5 / 3.7416f, 0, 0);
	//float3 xNegC = float3(0, 0, 0);
	//float3 yNegC = float3(0, 0, 0);
	//float3 zNegC = float3(0, 0, 0);

	//float3 xPosC2 = float3(0, 0, 0);
	//float3 yPosC2 = float3(0, 0, 0);
	//float3 zPosC2 = float3(0, 0, 0);
	//float3 xNegC2 = float3(0, 0, 1);
	//float3 yNegC2 = float3(0, 0, 0);
	//float3 zNegC2 = float3(0, 0, 0);

	//
	//lightAcc += max(0,  N.x * (gTime * xPosC + (1-gTime) * xPosC2));
	//lightAcc += max(0,  N.y * (gTime * yPosC + (1-gTime) * yPosC2));
	//lightAcc += max(0,  N.z * (gTime * zPosC + (1-gTime) * zPosC2));
	//lightAcc += max(0, -N.x * (gTime * xNegC + (1-gTime) * xNegC2));
	//lightAcc += max(0, -N.y * (gTime * yNegC + (1-gTime) * yNegC2));
	//lightAcc += max(0, -N.z * (gTime * zNegC + (1-gTime) * zNegC2));

	return float4(lightAcc * float3(1.0f, 1.0f, 1.0f), 1.0f);
}

technique11 tech
{
	pass P0
	{
		SetVertexShader( CompileShader( vs_5_0, VS() ) );
		SetGeometryShader( NULL );
		SetPixelShader( CompileShader( ps_5_0, PS() ) );
		
		SetDepthStencilState(DepthOn, 0);
		SetBlendState( NoBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
		SetRasterizerState(CullBack);
	}
}
